// 使用泛型可以增加代码拓展性和通用性
function identity<T, U>(value: T, msg: U): T {
  return value;
}

identity(1, 2);

// 泛型接口
//1.函数应用泛型接口
interface Identities<V, M> {
  value: V;
  msg: M;
}

function identity2<T, U>(value: T, msg: U): Identities<T, U> {
  let identities: Identities<T, U> = {
    value,
    msg,
  };
  return identities;
}

// console.log(identity2(68, "Semlinker"));

// 在类中应用泛型接口
interface GenericInteface<U = string> {
  value: U;
  getValue: () => U;
}

class Generic<T> implements GenericInteface<T> {
  value: T;
  constructor(value: T) {
    this.value = value;
  }
  getValue(): T {
    return this.value;
  }
}

let myGeneric = new Generic("kate");
// console.log(myGeneric);

// 四、泛型约束
// 4.1 确保属性存在
interface Length {
  length: number;
}
// function identity3<T extends Length>(arr: T): T {
//   console.log(arr.length);
//   return arr;
// }

// function identity3<T>(arr: Array<T>): Array<T> {
//   console.log(arr.length);
//   return arr;
// }

function identity3<T>(arr: T[]): T[] {
  console.log(arr.length);
  return arr;
}
identity3([1]);

// 4.2 检查对象上的键是否存在
type K1 = keyof Length[];

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

// 五、泛型参数默认类型
interface GenericInteface2<U = string> {
  value: U;
  getValue: () => U;
}

// 六、泛型条件类型
interface Dictionary<T = any> {
  [key: string]: T;
}

type StrDict = Dictionary<string>;

type DictMember<T> = T extends Dictionary<infer V> ? V : never;

type StrDictMember = DictMember<StrDict>;

// 获取 Promise 对象的返回值类型
async function stringPromise() {
  return "Hello world";
}

async function personPromise() {
  return { name: "znlm", age: 30 };
}

type PromiseType<T> = (args: any[]) => Promise<T>;
type UnPromisify<T> = T extends PromiseType<infer V> ? V : never;

type extractStringPromise = UnPromisify<typeof stringPromise>; // string
type extractPersonPromise = UnPromisify<typeof personPromise>; // Person
